#include <iostream>
/**
 * 3 fundamental properties of which a computer program must keep track when it stores data
 * 1. Where the information is stored
 * 2. What value is kept there
 * 3. What kind of information is stored
 * 
 * One stratergy form accomplishing these ends: defining a simple variable.
 * Second stratergy is based on pointers, which are variables that store addresses of values rather than the values themselves
 * 
*/
using namespace std;

struct Person{
    char name[20]; //
    int age; //
};

struct House{
    Person * pp;
};

struct City{
    House * hp;
};

void case_1(){
int d = 6;
    double c = 5;
    double *cp = &c;
    cout<<"d value: "<<d<<endl;
    cout<<"d "<<"address"<<": "<<&d<<endl;
    cout<<"c value: "<<c<<endl;
    cout<<"c "<<"address"<<": "<<cp<<"\t"<<&c<<endl;
    cout<<"cp "<<"address"<<":"<<&cp<<"\t cp value: "<<*cp<<endl;
}

void case_2(){
    double wages[3] {100.0, 200.0, 300.0};
    short stacks[3] {3,2,1};
    double * pw = wages;
    short * ps = &stacks[0];
    cout<<"*ps: "<<*ps<<endl; // Dereferencing a pinter means referring to the pointed-to value.
    ps++;
    ps++;
    ps++; // overstep the boundary
    ps++; // overstep the boundary
    cout<<"ps++ : "<<*ps<<endl;
}

/**
 * pointer point to pointer
*/
void case_3(){
    int a = 10;
    int * ap = &a;
    int ** app = &ap;
    cout<<"a val : "<<a<<" a addr : "<<&a<<endl;
    cout<<"ap val : "<<ap<<" ap addr : "<<&ap<<endl;
    cout<<"app val : "<<app<<" app addr : "<<&app<<endl;
}

void case_4(){
    Person p {"wanghongbin", 18};
    House h {&p};
    City c{&h};
    cout<<"c addr : "<<&c<<endl;
    cout<<"h addr : "<<&h<<endl;
    cout<<"p addr : "<<&p<<endl;
}

void case_5(){
    // Dynamic binding and static binding for arrays
    int tacos[10]; // static binding
    int size = 455;
    int * pz = new int [size]; // dynamic binding, size set at run time
    delete [] pz;

    // Using bracket array notation is equivalent to dereferencing a pointer
    // tacos[3] means *(tacos + 3) equivalent to tacos_p + 3
}

void case_6(){
    // using new to create dynamic structures
    Person * p_arr[3];
    for (int i = 0; i < 3; i++)
    {
        //Person p {"whb", i};
        p_arr[i] = new Person;
        p_arr[i]->name[0] = 'w';
        p_arr[i]->age = i;
    }
    
}

void case_7(){
    // block is a section of code enclosed between braces.
    {
        int a = 10;
    }
    // cout<<a<<endl; // not allowed, a is not defined in here.
}

void case_8(){
    // Arrays int a[4]; // a array contains 4 eles
    // Vector vector<int> a(4); // a vector contains 4 eles
    // array<int, 4> // array object of 4 ints
}

int main(){
    case_4();
    return 0;
}